﻿using System.Windows.Controls.Primitives;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows;

namespace Zero.UControl.Base.Helper.Base.UAdorner
{
    // 用于在被装饰元素周围绘制选择框及控制点的装饰器类
    internal class SelectionAdorner : Adorner
    {
        private readonly DrawingTool _tool;
        private readonly VisualCollection _visuals;
        private readonly Thumb[] _thumbs = new Thumb[9];
        private readonly Pen _borderPen = new Pen(new SolidColorBrush(Color.FromArgb(120, 0, 120, 215)), 1)
        {
            DashStyle = DashStyles.Dash
        };


        public SelectionAdorner(UIElement adorned, DrawingTool tool) : base(adorned)
        {
            _tool = tool;
            _visuals = new VisualCollection(this);
            BuildThumbs(); // 构建 9 个控制点
            // 注册触控手势事件：变换 + 惯性（拖动、缩放、旋转）
            AddHandler(UIElement.ManipulationDeltaEvent, new EventHandler<ManipulationDeltaEventArgs>(OnManipulation));
            AddHandler(UIElement.ManipulationInertiaStartingEvent, new EventHandler<ManipulationInertiaStartingEventArgs>(OnInertia));
        }

        // 构建 9 个 Thumb 控制点（8缩放+1旋转）
        private void BuildThumbs()
        {
            for (int i = 0; i < 9; i++)
            {
                var t = new Thumb
                {
                    Width = 10,
                    Height = 10,
                    Background = i == 8 ? Brushes.Gold : Brushes.White, 
                    BorderBrush = Brushes.Black,
                    BorderThickness = new Thickness(1)
                };
                _visuals.Add(t);
                _thumbs[i] = t;
                if (i == 8)
                    t.DragDelta += OnRotate; // 第9个用于旋转
                else
                    t.DragDelta += OnResize; // 其余用于缩放
            }
        }

        // 缩放处理逻辑（拖动控制点）
        private void OnResize(object sender, DragDeltaEventArgs e)
        {
            if (AdornedElement is not FrameworkElement fe) return;

            var idx = Array.IndexOf(_thumbs, sender); // 当前拖动的是哪个控制点

            // 根据索引判断拖动的是哪个方向
            bool left = idx is 0 or 3 or 5;
            bool right = idx is 2 or 4 or 7;
            bool top = idx is 0 or 1 or 2;
            bool bottom = idx is 5 or 6 or 7;

            // 计算新的宽高，根据拖动方向和鼠标变化量
            double newW = fe.ActualWidth + (right ? e.HorizontalChange : left ? -e.HorizontalChange : 0);
            double newH = fe.ActualHeight + (bottom ? e.VerticalChange : top ? -e.VerticalChange : 0);

            // 限制最大最小缩放范围
            newW = Math.Clamp(newW, 20, fe.ActualWidth * _tool.MaxScale);
            newH = Math.Clamp(newH, 20, fe.ActualHeight * _tool.MaxScale);

            // 如果缩放是从左/上方向拖动，需要调整位置
            double dx = left ? fe.ActualWidth - newW : 0;
            double dy = top ? fe.ActualHeight - newH : 0;

            // 设置新宽高
            fe.Width = newW;
            fe.Height = newH;

            // 更新控件位置
            Canvas.SetLeft(fe, Canvas.GetLeft(fe) + dx);
            Canvas.SetTop(fe, Canvas.GetTop(fe) + dy);

            InvalidateArrange(); // 重新排列子元素（更新Thumb位置）
        }

        // 旋转处理逻辑（拖动旋转点）
        private void OnRotate(object sender, DragDeltaEventArgs e)
        {
            if (AdornedElement is not UIElement el) return;

            Point center = GetCenter(el); // 获取元素中心点
            Point cur = Mouse.GetPosition(Parent as IInputElement); // 获取鼠标当前相对画布位置
            Vector v = cur - center; // 当前向量
            double angle = Math.Atan2(v.Y, v.X) * 180 / Math.PI + 90; // 计算角度

            el.RenderTransformOrigin = new Point(0.5, 0.5); // 旋转中心设为中心点
            if (el.RenderTransform is not RotateTransform rt)
            {
                rt = new RotateTransform(0);
                el.RenderTransform = rt;
            }
            rt.Angle = angle; // 设置旋转角度
        }

        // 获取元素中心点
        private static Point GetCenter(UIElement el)
        {
            return new(
                Canvas.GetLeft(el) + ((FrameworkElement)el).ActualWidth / 2,
                Canvas.GetTop(el) + ((FrameworkElement)el).ActualHeight / 2
            );
        }

        // 处理触控缩放、旋转、拖动
        private void OnManipulation(object sender, ManipulationDeltaEventArgs e)
        {
            if (AdornedElement is not FrameworkElement fe) return;

            var delta = e.DeltaManipulation; // 获取当前手势变化数据

            // 缩放
            double scale = delta.Scale.X;
            if (Math.Abs(scale - 1) > 0.01)
            {
                var st = fe.RenderTransform as ScaleTransform ?? new ScaleTransform(1, 1);
                fe.RenderTransformOrigin = new Point(0.5, 0.5);
                fe.RenderTransform = st;

                double newS = st.ScaleX * scale;
                if (newS < _tool.MinScale || newS > _tool.MaxScale)
                    scale = 1; // 超出限制就不缩放

                st.ScaleX *= scale;
                st.ScaleY *= scale;
            }

            // 旋转
            if (Math.Abs(delta.Rotation) > 0.01)
            {
                var rt = fe.RenderTransform as RotateTransform ?? new RotateTransform(0);
                fe.RenderTransformOrigin = new Point(0.5, 0.5);
                fe.RenderTransform = rt;
                rt.Angle += delta.Rotation * 180 / Math.PI;
            }

            // 平移（拖动）
            Canvas.SetLeft(fe, Canvas.GetLeft(fe) + delta.Translation.X);
            Canvas.SetTop(fe, Canvas.GetTop(fe) + delta.Translation.Y);

            e.Handled = true; // 事件已处理
            InvalidateArrange(); // 重新布局
        }

        // 设置触控惯性效果
        private void OnInertia(object sender, ManipulationInertiaStartingEventArgs e)
        {
            e.TranslationBehavior.DesiredDeceleration = 10 * 96.0 / (1000 * 1000); // 平移减速度（像素/毫秒²）
            e.ExpansionBehavior.DesiredDeceleration = 0.1; // 缩放惯性减速度
            e.RotationBehavior.DesiredDeceleration = 720 / (1000 * 1000); // 旋转惯性减速度（度/毫秒²）
        }

        #region Arrange / Visual children override

        // 定义控制点位置（Arrange 阶段）
        protected override Size ArrangeOverride(Size finalSize)
        {
            if (AdornedElement is not FrameworkElement fe) return finalSize;

            // 获取被装饰元素的位置和大小
            double l = Canvas.GetLeft(fe),
                   t = Canvas.GetTop(fe),
                   w = fe.ActualWidth,
                   h = fe.ActualHeight;

            // 定义9个Thumb的布局位置（控制点坐标）
            (double x, double y)[] pos =
            {
                (l-5, t-5),             // 左上
                (l + w/2-5, t-5),       // 上中
                (l + w-5, t-5),         // 右上
                (l-5, t + h/2-5),       // 左中
                (l + w-5, t + h/2-5),   // 右中
                (l-5, t + h-5),         // 左下
                (l + w/2-5, t + h-5),   // 下中
                (l + w-5, t + h-5),     // 右下
                (l + w/2-7, t-25)       // 上方旋转点
            };

            // 为每个Thumb设置布局位置
            for (int i = 0; i < _thumbs.Length; i++)
                _thumbs[i].Arrange(new Rect(pos[i].x, pos[i].y, _thumbs[i].Width, _thumbs[i].Height));

            return finalSize;
        }

        // 获取可视子元素数量
        protected override int VisualChildrenCount => _visuals.Count;

        // 获取指定索引的可视子元素
        protected override Visual GetVisualChild(int index) => _visuals[index];

        // 绘制选择框边框
        protected override void OnRender(DrawingContext dc)
        {
            if (AdornedElement is not FrameworkElement fe) return;

            dc.DrawRectangle(
                null, // 无填充
                _borderPen,
                new Rect(Canvas.GetLeft(fe), Canvas.GetTop(fe), fe.ActualWidth, fe.ActualHeight)
            );
        }

        #endregion
    }

}
